/*
 * @Author: Jone XIn
 * @Date: 2022-01-19 20:05:00
 * @LastEditTime: 2022-01-23 22:30:33
 * @Description: 观察文件夹的变动同步信息'
 * 1, 自动忽略 node_modules 和 package-lock.json 中的文件信息
 */
const chokidar = require('chokidar');
const path = require('path');
const queue = require('queue');
const md5 = require('md5');
const fs = require('fs-extra');
const { Project } = require('../model/project');
class Watcher {

    project_name = ''; // 项目名
    project_path = ''; // 项目路径【绝对】
    sync_id = ''; // 标识项目的唯一ID
    error = ''; // 错误信息
    wsClient = null; //ws 客户端
    content = {}; // ws 客户端连接的key 和 mid 的对象
    initerd = false;
    static that = null;


    constructor(project_name, project_path, sync_id, wsClient, content) {
        // 初始化
        // 初始化项目信息
        this.project_name = project_name || 'test';
        this.project_path = project_path || path.join(__dirname, '../utils/test');
        this.sync_id = sync_id;
        this.wsClient = wsClient;
        this.content = content;

        // 初始化队列
        this.fileInfoQueue = queue({ concurrency: 1, autostart: true });
        // 初始化文件的监控信息
        this.watcher = chokidar.watch(this.project_path, {
            ignored: ['node_modules', 'package-lock.json'], // 忽略的文件列表
            persistent: true
        });

        this.watcher
            .on('add', this.handFileAdd.bind(this))
            .on('change', this.handChange.bind(this))
            .on('unlink', this.handDeleteFile.bind(this))
            .on('addDir', this.handAddDir.bind(this))
            .on('unlinkDir', this.handDeleteDir.bind(this))
            .on('error', this.handError)
            .on('ready', this.init.bind(this))
    }

    async init() {
        console.log('文件监控开始!');
        this.initerd = true;
        // 将房间信息同步到mysql
        await Project.addProject({
            project_name: this.project_name,
            project_path: this.project_path,
            sync_id: this.sync_id,
            m_id: this.content.m_id,
            con_key: this.content.con_key,
            gen_time: Date.now()
        });
        console.log('创建房间成功!');
    }

    /**
     * 文件改变
     * @param {string} path
     */
    handChange(filePath) {
        console.log(filePath, '文件改变了');
        try {
            if (this.judgeFileStatus(filePath) && this.initerd) {
                const fileBuffer = fs.readFileSync(filePath);
                this.doTask({
                    sync_id: this.sync_id, data: fileBuffer, filePath, type: 'update'
                });
            }
        } catch (_) {
            console.log(_);
        }
    }

    /**
     * 将任务推进queue
     * @param {Object} fileInfo
     */
    doTask(fileInfo) {
        // 任务push进队列
        this.fileInfoQueue.push(
            (cb) => {
                // 上传ws服务端
                const status = this.wsClient.sendNewsText(fileInfo);
                if (status) console.log('发送成功');
                cb();
            }
        );
    }

    /**
     * 判断文件是否更新
     * @param {string} updateFilePath 文件路径
     * @returns boolean
     */
    judgeFileStatus(updateFilePath) {
        let currentMd5 = md5(fs.readFileSync(updateFilePath))
        if (currentMd5 == this.preveMd5) {
            console.log('文件无更新');
            return false;
        }
        this.preveMd5 = currentMd5;
        return true;
    }
    handFileAdd(filePath) {
        console.log(filePath, '文件增加了');
        if (!this.initerd) return;
        this.doTask({
            sync_id: this.sync_id,
            data: '',
            filePath,
            type: 'addFile'
        });
    }
    handDeleteFile(filePath) {
        console.log(filePath, '文件被删了');
        if (!this.initerd) return;
        this.doTask({
            sync_id: this.sync_id,
            data: '',
            filePath,
            type: 'deleteFile'
        });
    }
    handAddDir(filePath) {
        console.log(filePath, '文件夹增加了');
        if (!this.initerd) return;
        this.doTask({
            sync_id: this.sync_id,
            data: '',
            filePath,
            type: 'addDir'
        });
    }
    handDeleteDir(filePath) {
        console.log(filePath, '文件夹被删了');
        if (!this.initerd) return;
        this.doTask({
            sync_id: this.sync_id,
            data: '',
            filePath,
            type: 'deleteDir'
        });
    }
    handError(err) {
        console.log(err, '发生错误了');
    }
}

// new Watcher();
module.exports = Watcher